let arr = [10, 25, 13, 2, 16];
// 获取数组中的最大值和最小值

// 方案三：假设法
/* let max = 0; //假设0是最大值
arr.forEach(item => {
    // 依次迭代数组中的每一项，拿每一项和假设值做对比
    if (item > max) {
        // 如果假设是失败的，则重新假设
        max = item;
    }
});
console.log(max);
*/

// 方案二：排序
/* arr.sort((a, b) => b - a);
console.log(arr[0]);
console.log(arr[arr.length - 1]); */

// 方案一：基于Math.max/min处理
/* // 注意：方法要求要把数字一项项的传递进来才可以
console.log(Math.max(arr)); //NaN
console.log(Math.max([10, 25, 13, 2, 16])); //NaN
console.log(Math.max(10, 25, 13, 2, 16)); //25 */
/* console.log(Math.max(...arr)); //可以基于ES6的展开运算符“把数组每一项展开后，一项项传递给max函数”
console.log(Math.max.apply(Math, arr)); */

//====================
/* "use strict";
const fn = function fn(x, y) {
    console.log(this, x, y);
};
let obj = {
    name: 'obj'
};
let body = document.body;

body.onclick = fn; //点击的时候才会执行fn  this->body  x->事件对象  y->undefined
// body.onclick = fn(); //立即把fn执行，把执行的返回值赋值给click事件  body.onclick=undefined
// 需求：点击的时候才执行fn，并且让其中的this指向obj，传递10/20
// body.onclick = fn.call(obj, 10, 20); //这样实现不了：在绑定期间(还没点击)，call就把fn立即执行了
body.onclick = fn.bind(obj, 10, 20); */

//====================
/*
fn(10, 20); //this->undefined(window) x->10 y->20
fn.call(obj, 10, 20); //this->obj x->10 y->20
fn.call(10, 20); //this->10 x->20 y->undefined
fn.call(null, 10, 20); //this->null(window) x->10 y->20
fn.call(); //this->undefined(window) x->undefined y->undefined
*/

/* fn.call(obj, ...[10, 20]);
fn.apply(obj, [10, 20]); //this->obj x->10 y->20 */

//====================
// obj.fn(10, 20); //Uncaught TypeError: obj.fn is not a function  此时obj和fn没有任何关系
// 我的需求是：把fn执行，让fn中的this是obj，并且传递10,20
/* 
 Function.prototype具备三个方法：call/apply/bind，每一个函数都是Function内置类的实例，所以都可以使用这三个方法！！ 
   + 三个方法都是用来“强制”改变函数中this指向的「语法上有一些区别」
   + 但是对箭头函数无效

 函数.call(context,params1,params2,....)
   作用：把函数执行，让函数中的this指向第一个参数context，并且把params1/params2...当做实参传递给函数
   操作步骤：
     首先函数基于__proto__找到Function.prototype.call方法
     然后把找到的call方法执行
     最后在call方法执行的过程中
        + 帮我们把函数中的this改为context了
        + 帮我们把函数执行了，把实参也传递给它了
        + ...

 函数.apply(context,[params1,params2,....])
   apply和call方法的唯一区别是：传递给函数的实参，需要放在一个数组集合中，而不是一项项零散的传递；但是最后的效果还是把集合中的每一项，分别传递给函数！！

 函数.bind(context,params1,params2,....)
   bind和call方法的唯一区别是：call是把函数“立即执行”，而bind是“预处理”函数中的this和参数，不会立即执行
 */
